﻿using System;
using System.Threading;
using System.Data.Linq;
using System.Transactions;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Plat.WfProcess.Common;
using Plat.WfProcess.DataModel;
using Plat.WfProcess.Business;
using Plat.WfProcess.Utility;

namespace Plat.WfProcess.Engine
{
    /// <summary>
    /// 流程运行类
    /// </summary>
    public class WfRunnerInstance
    {

        #region WfRunner属性列表

        private long _ApplicationInstanceID;
        private long _TaskID;
        private ActivityResource _ActivityResource;
        private ProcessEntity _ProcessEntity;

        private event EventHandler<WfRunnerInstanceCompletedEventArgs> wfRunnerInstanceCompleted;
        public event EventHandler<WfRunnerInstanceCompletedEventArgs> WfRunnerInstanceCompleted
        {
            add
            {
                wfRunnerInstanceCompleted += value;
            }
            remove
            {
                wfRunnerInstanceCompleted -= value;
            }

        }
        
        public WfRuntimeManager WfRuntimeManager
        {
            get;
            set;
        }

        /// <summary>
        /// 工作项执行结果
        /// </summary>
        internal WorkItemExecutedResult WorkItemExecutedResult
        {
            get;
            set;
        }

        /// <summary>
        /// 下一步活动列表的匹配结果
        /// </summary>
        internal NextActivityMatchedResult NextActivityMatchedResult
        {
            get;
            set;
        }
        #endregion

        #region WfRunner 构造函数
        public WfRunnerInstance(long applicationInstanceID, 
            string processGUID,
            ActivityResource activityResource)
        {
            ProcessManager pManager = new ProcessManager();
            _ProcessEntity = pManager.Select(processGUID);
            _ApplicationInstanceID = applicationInstanceID;

            _ActivityResource = activityResource;
        }

        public WfRunnerInstance(long taskID,
            ActivityResource activityResource)
        {
            _TaskID = taskID;
            _ActivityResource = activityResource;
        }
        #endregion

        #region 流程启动
        /// <summary>
        /// 流程启动执行
        /// </summary>
        /// <returns></returns>
        public bool StartProcess()
        {
            try
            {
                Thread thread = new Thread(SetupProcessInstance);
                thread.Start();

                return true;
            }
            catch (System.Exception ex)
            {
                throw;
            }
        }

        /// <summary>
        /// 启动流程
        /// </summary>
        internal void SetupProcessInstance()
        {
            //写入流程实例
            ProcessInstanceEntity processInstance = new ProcessInstanceManager(_ApplicationInstanceID, _ProcessEntity.ProcessGUID)
                .CreateNewProcessInstanceObject(_ProcessEntity);

            //写入活动实例
            //1. 获取开始节点活动
            ActivityManager am = new ActivityManager(_ProcessEntity.ProcessGUID);
            ActivityEntity startActivity = am.GetStartActivity();

            ActivityExecutionContext startExecutionObject = new ActivityExecutionContextStart(processInstance,
                startActivity,
                _ActivityResource);

            ExecuteWorkItemIteraly(startExecutionObject);

            if (wfRunnerInstanceCompleted != null)
            {
                WfRunnerInstanceCompletedEventArgs args = new WfRunnerInstanceCompletedEventArgs();
                args.ProcessInstanceGUID = processInstance.ProcessInstanceGUID;
                args.WorkItemExecutedResult = WorkItemExecutedResult;
                args.NextActivityMatchedResult = NextActivityMatchedResult;
                wfRunnerInstanceCompleted(this, args);
            }
        }
        #endregion

        #region 流程运行
        /// <summary>
        /// 流程执行
        /// </summary>
        /// <returns></returns>
        public bool RunProcess()
        {
            try
            {
                Thread thread = new Thread(RunProcessInstance);
                thread.Start();

                return true;
            }
            catch (WfRuntimeException rex)
            {
                throw;
            }
            catch (System.Exception ex)
            {
                //throw new WfRuntimeException(string.Format("流程运行发生错误，详细信息:{0}", ex.Message), ex);
                throw;
            }
        }

        /// <summary>
        /// 流程运行
        /// </summary>
        internal void RunProcessInstance()
        {
            ActivityExecutionContext runningExecutionObject = new ActivityExecutionContexttRunning(_TaskID, 
                _ActivityResource);

            //判断流程是否可以被运行
            if (runningExecutionObject.ProcessInstance.State == (short)ProcessStateEnum.Running)
            {
                //判断当前任务的活动是否处于可办理状态
                TaskManager tm = new TaskManager();
                TaskViewEntity taskView = tm.Select(_TaskID);
                if (taskView.ActivityState == (short)NodeStateEnum.Running)
                {
                    ExecuteWorkItemIteraly(runningExecutionObject);
                }
                else
                {
                    throw new WfRuntimeException(string.Format("当期当前活动节点不在运行状态！详细信息：当前活动状态：{0}", taskView.ActivityState));
                }
            }
            else
            {
                throw new WfRuntimeException(string.Format("当期流程不在运行状态！详细信息：当前流程状态：{0}", runningExecutionObject.ProcessInstance.State));
            }

            if (wfRunnerInstanceCompleted != null)
            {
                WfRunnerInstanceCompletedEventArgs args = new WfRunnerInstanceCompletedEventArgs();
                args.ProcessInstanceGUID = runningExecutionObject.ProcessInstance.ProcessInstanceGUID;
                args.WorkItemExecutedResult = WorkItemExecutedResult;
                args.NextActivityMatchedResult = NextActivityMatchedResult;
                wfRunnerInstanceCompleted(this, args);
            }
        }

        #endregion

        /// <summary>
        /// 执行要办理的工作项
        /// </summary>
        /// <param name="processInstanceEntity"></param>
        internal void ExecuteWorkItemIteraly(ActivityExecutionContext activityExecutionObject)
        {
            NodeMediator mediator = NodeMediatorFactory.CreateWorkItemMediator(activityExecutionObject);
            mediator.ExecuteWorkItem();

            //继续执行队列中的节点
            Queue<WorkItem> toDoQueue = mediator.ToDoAutoWorkItemQueue;
            while (toDoQueue.Count > 0)
            {
                //更新执行上下文数据
                WorkItem workItem = toDoQueue.Dequeue();
                activityExecutionObject.Activity = workItem.Activity;
                activityExecutionObject.ActivityInstance = workItem.ActivityInstance;

                //继续向前执行...
                NodeMediator nextMediator = NodeMediatorFactory.CreateWorkItemMediator(activityExecutionObject);
                nextMediator.ExecuteWorkItem();

                toDoQueue = nextMediator.ToDoAutoWorkItemQueue;
            }
        }

    }
}
